#include "Tcpserver.hpp"
#include "Log.hpp"
#include "Calculator.hpp"
#include "Protocol.hpp"
#include <memory>

using namespace LogMoudle;

using cal_func = std::function<Response(const Request &req)>;

class Parse
{
private:
    cal_func _cal;

public:
    Parse(cal_func c) : _cal(c)
    {
    }

    // 函数处理入口
    std::string Entry(std::string &package)
    {
        std::string message; // 去除报文长度结果
        std::string respstr; // 最终的处理结果

        // 将接收的报文序列化，传入message
        while (Decode(package, &message))
        {
            // 判断报文的完整性
            LOG(Logevel::INFO) << "Content: \n"
                               << message;
            if (message.empty())
            {
                break;
            }

            // 反序列化
            Request req;

            if (!req.Deserialize(message))
            {
                break;
            }

            std::cout << "###############" << std::endl;
            req.Print();
            std::cout << "###############" << std::endl;

            // 计算
            Response resp = _cal(req);
            std::cout<<"计算成功"<<std::endl;

            // 序列化
            std::string res;
            resp.Serialize(res);
            LOG(Logevel::INFO) << "序列化： \n"
                               << res;

            // 添加报文长度字段
            Encode(res);

            LOG(Logevel::INFO) << "Encode: \n"
                               << res;

            // 拼接应答
            respstr += res;
        }
        return respstr;
    }
};

// 对于序列化和反序列化的练习

int main()
{
    // 这里我们直接使用默认的端口号

    Calculator mycal;
    // 解析对象
    Parse myprase([&mycal](const Request &req)
                  { return mycal.Execute(req); 
                }
    );

    //只负责通信，将相应的反序列化后添加报文长度的报文传输给相应的处理函数
    std::shared_ptr<Tcpserver> ser = std::make_shared<Tcpserver>([&myprase](std::string &package)
                                                                 { return myprase.Entry(package);
                                                                }
    );


    ser->Initserver();
    ser->Startserver();

    return 0;
}